
package net.swa.file.web.action;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;
import net.swa.file.beans.entity.Attachment;
import net.swa.system.beans.entity.User;
import net.swa.system.service.ICommonService;
import net.swa.system.util.annotation.Log;
import net.swa.system.web.action.AbstractBaseAction;
import net.swa.util.BuzConst;
import net.swa.util.EncryptTool;
import net.swa.util.FileUtil;
import net.swa.util.JsonResult;

public class FileAction extends AbstractBaseAction
{
    private static final long serialVersionUID = -3566256767528230895L;

    private final Logger log = Logger.getLogger(FileAction.class);

    /**存放上传文件的目录**/
    private String uploadPath;

    /**存放删除文件目录*/
    private String gabagePath;

    /**文件服务器路径**/
    private String httpPath;

    private File file;

    private String fileFileName;

    private String fileContentType;

    /**存放上传文件的目录的字目录，由于文件的分类，客户端传入**/
    private String folder;

    private int width;

    private int height;

    /**缩略后图片高宽*/
    private double outputWidth = 120;

    private double outputHeight = 120;

    /**文件类型名**/
    private String ext;

    /**文件大小**/
    private int size;

    private String imgUrl;

    /**是否要真的删除文件**/
    private boolean delete;

    private ICommonService commonService;

    /**
     * 删除文件
     * @return
     * @throws Exception
     */
    @Log(description = "删除文件图片")
    public String removeFile() throws Exception
    {
        //        UploadFile file = commonService.commonFind(UploadFile.class, fileId);
        Attachment file = commonService.findByAttribute(Attachment.class, "uuid", fileFileName);
        if (null != file)
        {
            if (delete)
            {
                commonService.commonDelete("Attachment", file.getId());
                String fname = fileFileName.replace(httpPath, "").replace("/", "");
                String path = fileFileName.replace(httpPath, uploadPath); //部署时候可配置
                File target = new File(path);
                File gcFile = new File(gabagePath);
                if (!gcFile.exists())
                {
                    gcFile.mkdirs();
                }
                //将文件移到新文件里 
                File fnew = new File(gabagePath + File.separator + fname);
                target.renameTo(fnew);
                target.delete();
            }
            outSuccess();
        }
        else
        {
            outError("附件不存在");
        }
        return null;
    }

    @Log(description = "下载文件图片")
    public String download() throws Exception
    {
        HttpServletResponse response = getResponse();
        String path = fileFileName.replace(httpPath, uploadPath); //部署时候可配置
        File target = new File(path);
        InputStream in = new FileInputStream(target);
        response.setHeader("Content-disposition", "attachment;filename=" + fileFileName);
        response.setIntHeader("Content-Length", in.available());
        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        try
        {
            bos = new BufferedOutputStream(response.getOutputStream());
            bis = new BufferedInputStream(in);
            byte[] b = new byte[1024];
            int len;
            while ((len = bis.read(b)) > 0)
            {
                bos.write(b, 0, len);
            }
            bos.flush();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            bos.close();
            bis.close();
        }
        return null;
    }

    /**
     * 验证文件大小
     * @return
     * @throws Exception
     */
    private boolean validateFileSize() throws Exception
    {
        if (this.size != 0)
        {
            /* 150 */InputStream in = new FileInputStream(this.file);
            /* 151 */int length = in.available();
            /* 152 */in.close();
            /* 153 */if (this.size * 1024 > length)
            {
                /* 154 */return false;
            }
        }
        /* 157 */return true;
    }

    /**
     * 上传文件
     * 并且保存附件表信息
     * @return
     * @throws Exception
     */
    public String upload() throws Exception
    {
        JsonResult<Object> json = new JsonResult<Object>();
        boolean mat = true;
        User u = getCurrentUser();
        if (null == u)
        {
            log.debug("session 为空，应该是session过期，或移动端调用");
            mat = false;
            String mac = getRequestParameter("mac");
            String token = getRequestParameter("token");
            if (!StringUtils.isBlank(token))
            {
                if (StringUtils.isBlank(mac))
                {
                    mac = BuzConst.DEFAULT_KEY;
                }
                EncryptTool tool;
                tool = new EncryptTool(mac);
                String sid = tool.decrypt(token);
                mat = sid.matches("\\d+");
                log.debug("移动端校验结果：" + mat);
            }
        }
        if (mat)
        {
            String path = uploadPath; //部署时候可配置
            String imgUrl = httpPath + folder + "/";
            File target = new File(path + File.separator + folder);
            if (!target.exists())
            {
                target.mkdirs();
            }
            File mintarget = new File(path + File.separator + folder + "/min/");
            if (!mintarget.exists())
            {
                mintarget.mkdirs();
            }

            String sourceName = fileFileName;
            String ext = FileUtil.getExtension(this.fileFileName);
            this.fileFileName = UUID.randomUUID().toString() + "." + ext;
            File desc = new File(target.getAbsoluteFile() + File.separator + this.fileFileName);

            String mindesc = mintarget.getAbsoluteFile() + File.separator + this.fileFileName;

            if (!(validateFile(this.ext, ext)))
            {
                json.setSuccess(false);
                json.setMessage("附件格式不符合要求");
            }
            else if (validateFileSize())
            {
                if (!(validateImage()))
                {
                    json.setSuccess(false);
                    json.setMessage("图片尺寸不符合要求");
                }
                else
                {
                    writeFile(this.file, desc, mindesc);
                    json.setSuccess(true);
                    //保存到附件表
                    Attachment attachment = new Attachment();
                    attachment.setName(sourceName);
                    attachment.setUuid(imgUrl + fileFileName);//此处也加路径？？
                    attachment.setExt(ext);
                    attachment.setPath(desc.getAbsolutePath());
                    commonService.commonAdd(attachment);
                    json.setAttribute("fileName", imgUrl + this.fileFileName);//此图片服务器上可以直接取？？
                    json.setAttribute("minfileName", imgUrl + "min/" + this.fileFileName);//此图片服务器上可以直接取？？
                    json.setAttribute("sourceName", sourceName);
                }
            }
            else
            {
                json.setSuccess(false);
                json.setMessage("附件大小不符合要求");
            }
        }
        else
        {
            json.setSuccess(false);
            json.setMessage("token 校验失败");
        }
        outJson(json);
        return null;
    }

    private void writeFile(File src , File desc , String mindesc)
    {
        try
        {
            FileInputStream inputStream = new FileInputStream(src);
            OutputStream outputStream = new FileOutputStream(desc);
            byte[] buf = new byte[1024];
            int length = 0;
            while ((length = inputStream.read(buf)) != -1)
            {
                outputStream.write(buf, 0, length);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
            Image img = ImageIO.read(desc);
            // 为等比缩放计算输出的图片宽度及高度 
            double rate1 = ((double) img.getWidth(null)) / (double) outputWidth + 0.1;
            double rate2 = ((double) img.getHeight(null)) / (double) outputHeight + 0.1;
            // 根据缩放比率大的进行缩放控制 
            double rate = rate1 > rate2 ? rate1 : rate2;
            int newWidth = (int) (((double) img.getWidth(null)) / rate);
            int newHeight = (int) (((double) img.getHeight(null)) / rate);
            BufferedImage tag = new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB);
            /*
             * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的
             * 优先级比速度高 生成的图片质量比较好 但速度慢
             * 
             */
            tag.getGraphics().drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
            FileOutputStream out = new FileOutputStream(mindesc);
            // JPEGImageEncoder可适用于其他图片类型的转换 
            //            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            //            encoder.encode(tag);
            ImageIO.write(tag, "JPEG", out);//将内存中的图片通过流动形式输出到客户端
            out.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 比较文件格式
     * @param ext1
     * @param ext2
     * @return
     * @throws Exception
     */
    private boolean validateFile(String ext1 , String ext2) throws Exception
    {
        if (ext1 != null)
        {
            return (ext1.equalsIgnoreCase(ext2));
        }

        return true;
    }

    /**
     * 校验图片规格
     * @return
     * @throws Exception
     */
    private boolean validateImage() throws Exception
    {
        if ((this.width != 0) && (this.height != 0))
        {
            FileInputStream in = new FileInputStream(this.file);
            BufferedImage img = ImageIO.read(in);

            return ((img.getWidth() == this.width) || (img.getHeight() == this.height));
        }

        return true;
    }

    /**
     * 写文件
     * @param src
     * @param desc
     * @throws Exception
     */
    private void writeFile(File src , File desc) throws Exception
    {
        try
        {
            FileInputStream inputStream = new FileInputStream(src);
            OutputStream outputStream = new FileOutputStream(desc);
            byte[] buf = new byte[1024];
            int length = 0;
            while ((length = inputStream.read(buf)) != -1)
            {
                outputStream.write(buf, 0, length);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    @Log(description = "查看图片")
    public String viewImg()
    {
        HttpServletResponse response = getResponse();
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        try
        {
            URL url = new URL(imgUrl);
            URLConnection con = url.openConnection();
            int index = imgUrl.indexOf("/", 10);
            con.setRequestProperty("Host", index == -1 ? imgUrl.substring(7) : imgUrl.substring(7, index));
            con.setRequestProperty("Referer", null);
            InputStream is = con.getInputStream();
            BufferedImage image = ImageIO.read(is);
            ImageIO.write(image, "png", response.getOutputStream());
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return null;
        }

        return null;
    }

    public File getFile()
    {
        /* 241 */return this.file;
    }

    public void setFile(File file)
    {
        /* 245 */this.file = file;
    }

    public String getFileFileName()
    {
        /* 249 */return this.fileFileName;
    }

    public void setFileFileName(String fileFileName)
    {
        /* 253 */this.fileFileName = fileFileName;
    }

    public String getFileContentType()
    {
        /* 257 */return this.fileContentType;
    }

    public void setFileContentType(String fileContentType)
    {
        /* 261 */this.fileContentType = fileContentType;
    }

    public static long getSerialVersionUID()
    {
        /* 265 */return 7350336710259585825L;
    }

    public String getFolder()
    {
        /* 269 */return this.folder;
    }

    public void setFolder(String folder)
    {
        /* 273 */this.folder = folder;
    }

    public String listPage() throws Exception
    {
        /* 294 */return null;
    }

    public int getWidth()
    {
        /* 298 */return this.width;
    }

    public void setWidth(int width)
    {
        /* 302 */this.width = width;
    }

    public int getHeight()
    {
        /* 306 */return this.height;
    }

    public void setHeight(int height)
    {
        /* 310 */this.height = height;
    }

    public String getExt()
    {
        /* 314 */return this.ext;
    }

    public void setExt(String ext)
    {
        /* 318 */this.ext = ext;
    }

    public int getSize()
    {
        /* 322 */return this.size;
    }

    public void setSize(int size)
    {
        /* 326 */this.size = size;
    }

    public String getUploadPath()
    {
        return this.uploadPath;
    }

    public void setUploadPath(String uploadPath)
    {
        this.uploadPath = uploadPath;
    }

    public String getGabagePath()
    {
        return gabagePath;
    }

    public void setGabagePath(String gabagePath)
    {
        this.gabagePath = gabagePath;
    }

    public ICommonService getCommonService()
    {
        return commonService;
    }

    @Resource
    @Required
    public void setCommonService(ICommonService commonService)
    {
        this.commonService = commonService;
    }

    public String getHttpPath()
    {
        return httpPath;
    }

    public void setHttpPath(String httpPath)
    {
        this.httpPath = httpPath;
    }

    public String getImgUrl()
    {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl)
    {
        this.imgUrl = imgUrl;
    }

    public boolean getDelete()
    {
        return delete;
    }

    public void setDelete(boolean delete)
    {
        this.delete = delete;
    }

    public double getOutputWidth()
    {
        return outputWidth;
    }

    public void setOutputWidth(double outputWidth)
    {
        this.outputWidth = outputWidth;
    }

    public double getOutputHeight()
    {
        return outputHeight;
    }

    public void setOutputHeight(double outputHeight)
    {
        this.outputHeight = outputHeight;
    }

}
